package com.mlan.userap.untils;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.google.android.datatransport.runtime.firebase.transport.LogEventDropped;
import com.google.gson.Gson;
import com.kongzue.baseokhttp.util.JsonBean;
import com.kongzue.baseokhttp.util.JsonMap;
import com.mlan.userap.AppConfig;
import com.mlan.userap.MyAPP;
import com.mlan.userap.model.MsgEvent;
import com.mlan.userap.model.MsgResp;
import com.mlan.userap.model.OpCode;

import org.greenrobot.eventbus.EventBus;
import org.json.JSONObject;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

public class WebSocketManager {

    private static final String TAG = "WebSocketManager";
    private static final long RECONNECT_INTERVAL = 2000; // 重连间隔 5 秒
    private static WebSocketManager instance;

    private OkHttpClient client;
    private WebSocket webSocket;
    private String wsUrl;
    private Map<String, String> headers;
    private Set<WebSocketListener> listeners;
    private boolean isConnecting;
    private Handler reconnectHandler;

    private WebSocketManager() {
        client = new OkHttpClient.Builder()
                .readTimeout(0, TimeUnit.MILLISECONDS)
                .writeTimeout(0, TimeUnit.MILLISECONDS)
                .connectTimeout(10, TimeUnit.SECONDS)
                .build();
        headers = new HashMap<>();
        listeners = new HashSet<>();
        reconnectHandler = new Handler(Looper.getMainLooper());
    }

    public static WebSocketManager getInstance() {
        if (instance == null) {
            synchronized (WebSocketManager.class) {
                if (instance == null) {
                    instance = new WebSocketManager();
                }
            }
        }
        return instance;
    }

    /**
     * 添加 WebSocket 监听器
     *
     * @param listener 监听器
     */
    public void addListener(WebSocketListener listener) {
        listeners.add(listener);
    }

    /**
     * 移除 WebSocket 监听器
     *
     * @param listener 监听器
     */
    public void removeListener(WebSocketListener listener) {
        listeners.remove(listener);
    }

    /**
     * 初始化 WebSocket 连接
     */
    public void connect() {
        this.wsUrl = AppConfig.WsUrl;
        this.headers.put("token", AppConfig.token);
        if (isConnecting) {
            LogHelper.e("WebSocket is already connecting");
            return;
        }

        Request.Builder requestBuilder = new Request.Builder().url(wsUrl);
        for (Map.Entry<String, String> entry : this.headers.entrySet()) {
            requestBuilder.addHeader(entry.getKey(), entry.getValue());
        }
        Request request = requestBuilder.build();

        webSocket = client.newWebSocket(request, new okhttp3.WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, okhttp3.Response response) {
                isConnecting = true;
                LogHelper.i("WebSocket connected");
                for (WebSocketListener listener : listeners) {
                    Log.d("zdl", "===WebSocketManager==102======开始重新连接===");
                    listener.onConnected();
                }
                stopReconnect();
            }

            @Override
            public void onMessage(WebSocket webSocket, String text) {
                RecData(text);
            }

            @Override
            public void onMessage(WebSocket webSocket, ByteString bytes) {
                String text = bytes.utf8();
                RecData(text);
            }

            @Override
            public void onClosing(WebSocket webSocket, int code, String reason) {
                isConnecting = false;
                Log.d(TAG, "WebSocket closing: " + code + ", " + reason);
                Log.d("zdl", "===WebSocketManager==onClosing==123====reason===" + reason);
                for (WebSocketListener listener : listeners) {
                    listener.onClosing(code, reason);
                }
            }

            @Override
            public void onClosed(WebSocket webSocket, int code, String reason) {
                isConnecting = false;
                Log.d(TAG, "WebSocket closed: " + code + ", " + reason);
                Log.d("zdl", "===WebSocketManager==onClosed==133====reason===" + reason);
                for (WebSocketListener listener : listeners) {
                    listener.onClosed(code, reason);
                }
                startReconnect();
            }

            @Override
            public void onFailure(WebSocket webSocket, Throwable t, okhttp3.Response response) {
                isConnecting = false;
                Log.e(TAG, "WebSocket failure: " + t.getMessage());
                for (WebSocketListener listener : listeners) {
                    listener.onFailure(t);
                }
                startReconnect();
            }
        });
    }

    private void RecData(String text) {
        Log.d("zdl","===========WebSocket======161=========text=========="+text);
        LogHelper.i("WebSocket Received: " + text);
        for (WebSocketListener listener : listeners) {
            listener.onMessage(text);
        }
        try {
            JSONObject recdata = new JSONObject(text);
            int tag = recdata.getInt("tag");
            if (tag > 0) {
                String code = recdata.getString("code");
                if (code.equals(OpCode.AppInfo.toString())) {

                } else if (code.equals(OpCode.AppScreen.toString())) {

                } else {
                    MsgEvent msgEvent = new MsgEvent();
                    msgEvent.tag = tag;
                    msgEvent.code = code;
                    msgEvent.message = recdata.getString("message");
                    msgEvent.requestId = recdata.getString("requestId");


                    if (code.equals(OpCode.Chat.toString())) {
                        MsgResp resp = MsgHelper.ChangeEntity(recdata.get("data"));
                        msgEvent.data = resp;
                        new Thread(() -> {
                            MyAPP.getApp().getChatDao().insertMessage(resp);
                        }).start();
                    } else {
                        msgEvent.data = recdata.get("data");
                    }
                    EventBus.getDefault().post(msgEvent);


                }
            } else {
                MyAPP.getApp().showToast(recdata.getString("message"));
            }
        }catch (Throwable e){

        }
    }

    /**
     * 发送消息
     *
     * @param data 消息内容
     * @return 是否发送成功
     */
    public boolean sendMessage(Object data) {
        String json = Convert.toJson(data);
        LogHelper.i("ws发送:" + json);
        ByteString byteString = ByteString.encodeUtf8(json);
        return sendMessage(byteString);
    }

    /**
     * 发送消息
     *
     * @param message 消息内容
     * @return 是否发送成功
     */
    public boolean sendMessage(String message) {
        LogHelper.i("text发送:" + message);
        if (webSocket != null && isConnecting) {
            return webSocket.send(message);
        }
        Log.e(TAG, "WebSocket is not connected, cannot send message");
        return false;
    }

    /**
     * 发送二进制消息
     *
     * @param bytes 二进制数据
     * @return 是否发送成功
     */
    public boolean sendMessage(ByteString bytes) {
        if (webSocket != null && isConnecting) {
            return webSocket.send(bytes);
        }
        Log.e(TAG, "WebSocket is not connected, cannot send binary message");
        return false;
    }

    /**
     * 断开连接
     */
    public void disconnect() {
        if (webSocket != null) {
            webSocket.close(1000, "Normal closure");
            webSocket = null;
            isConnecting = false;
            stopReconnect();
        }
    }

    /**
     * 启动重连机制
     */
    private void startReconnect() {
        reconnectHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (!isConnecting) {
                    Log.d(TAG, "Attempting to reconnect...");
                    connect();
                }
            }
        }, RECONNECT_INTERVAL);
    }

    /**
     * 停止重连
     */
    private void stopReconnect() {
        reconnectHandler.removeCallbacksAndMessages(null);
    }

    /**
     * WebSocket 监听器接口
     */
    public interface WebSocketListener {
        void onConnected();

        void onMessage(String message);

        void onMessage(ByteString bytes);

        void onClosing(int code, String reason);

        void onClosed(int code, String reason);

        void onFailure(Throwable t);
    }
}